package xyz.thoughtset.viewer.common.api.result;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;

import java.util.Collection;
import java.util.Objects;

@Data
@NoArgsConstructor
public class Result<T> {
    private Integer status;
    private String message;
    private Object data;
    private long count;
    private byte[] checkCode;
    private String key;


    public Result(Integer status, String message, Object data, long count,byte[] bytes) {
        this.status = status;
        this.message = message;
        this.data = data;
        this.count = count;
        signData(bytes);
    }

    public static <T> Result<T> success(T data,byte[] bytes) {
        return success(ResultEnum.SUCCESS.getMessage(), data, bytes);
    }

    @SneakyThrows
    public static <T> Result<T> success(String message, T data,byte[] bytes) {
        long num = 1;
        Object obj = data;
        if (Objects.nonNull(data)) {
            if (data instanceof Collection<?>) {
                num = ((Collection<?>) data).size();
            } else if (data.getClass().isArray()) {
                num = java.lang.reflect.Array.getLength(data);
            }
//        if (data instanceof Page) {
//            Page pages = (Page) data;
//            num = pages.getTotal();
//            obj = pages.getResults();
//        }
        } else {
            obj = null;
            num = 0;
        }
        return new Result<>(ResultEnum.SUCCESS.getStatus(), message, obj,num, bytes);
    }


    public static Result<?> failed(String message) {
        return new Result<>(ResultEnum.FAILED.getStatus(), message, null,0, StrUtil.utf8Bytes(message));
    }
    public static Result<?> notLogIn() {
        return failed(ResultEnum.NOTLOGIN);
    }

    public static Result<?> failed(ResultEnum errorResult) {
        return new Result<>(errorResult.getStatus(), errorResult.getMessage(), null,0, StrUtil.utf8Bytes(errorResult.getMessage()));
    }

    private Result signData(byte[] bytes){
        Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA);
        this.key = sign.getPublicKeyBase64();
        this.checkCode = sign.sign(bytes);
        return this;
    }

    public boolean verify(byte[] bytes){
        Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA,null,key);
        return !sign.verify(bytes,checkCode);
    }

    public boolean hasNotSuccess(){
        return !ResultEnum.SUCCESS.getStatus().equals(status);
    }


}